package com.anji.hyperneat.modular;

import java.io.File;
import java.util.ArrayList;

import org.jgap.Chromosome;

import com.anji.hyperneat.nd.ActivatorND;
import com.anji.hyperneat.nd.NDActivatorArray;
import com.anji.hyperneat.nd.NDFloatArray;
import com.anji.neat.Evolver;
import com.anji.util.Properties;

public class NonTugTestFF extends ModularHyperNeatFitnessFunction {

	@Override
	public int getMaxFitnessValue() {
		return 1000;
	}

	@Override
	protected int evaluate(Chromosome genotype, NDActivatorArray substrate,
			int evalThreadIndex) {
		int coord = Math.random() * 2 > 1 ? 3 : 2;
		int color = 0;
		NDFloatArray inputs = new NDFloatArray(new int[] {6,2});
		NDFloatArray outs;
		ActivatorND sub;
		boolean[] visited = new boolean[6];
		for (int i = 0; i < visited.length; i++) visited[i] = false;
		
		boolean capturedLeft = false;
		boolean capturedRight = false;
		int stayedGreenOnLeft = 0;
		int stayedRedOnRight = 0;
		int timeOnLeft = 0;
		int timeOnRight = 0;
		
		ArrayList<Float> metrics = new ArrayList<Float>(4);
		
		
		for (int time = 0; time < 8; time++) {
			if (coord > 2) {
				sub = substrate.get(1);
			} else {
				sub = substrate.get(0);
			}
			
			inputs.clear();
			inputs.set(1.0f, coord, 0);
			for (int i = 0; i < visited.length; i++) {
				if (visited[i]) {
					inputs.set(0.0f, i, 1);
				} else {
					inputs.set(1.0f, i, 1);
				}
			}
			
			
			outs = sub.next(inputs);
			
			if (outs.get(0, 0) > outs.get(1, 0)) color = 0;
			else color = 1;
			
			if (outs.get(2, 0) > outs.get(3, 0)) coord -= 1;
			else coord += 1;
			
			if (coord < 0) coord = 0;
			if (coord > 5) coord = 5;
			
			visited[coord] = true;
			
			// Fitness
			if (coord < 3) {
			// If it's on the left side
				timeOnLeft++;
				if (color == 0) stayedGreenOnLeft++;
				if (coord == 0) capturedLeft = true;
				
			} else {
			// Otherwise, it's on the right side
				timeOnRight++;
				if (color == 1) stayedRedOnRight++;
				if (coord == 5) capturedRight = true;
			}
			
		}
		
		// stayed Green on Left
		metrics.add(timeOnLeft > 0 ? (float)stayedGreenOnLeft / timeOnLeft : 0.0f);
		
		metrics.add(timeOnRight > 0 ? (float)stayedRedOnRight / timeOnRight : 0.0f);
		
		float capVal = 0.0f;
		if (capturedLeft) capVal += 0.5;
		if (capturedRight) capVal += 0.5;
		
//		metrics.set(2, capturedLeft ? 1.0f : 0.0f);
//		
//		metrics.set(3, capturedRight ? 1.0f : 0.0f);
		metrics.add(capVal);
		
		float fitness = 0.0f;
		fitness += metrics.get(0);
		fitness += metrics.get(1);
		fitness += metrics.get(2);
		fitness /= 3;
		
		if (fitness == 1.0f) genotype.setPerformanceValue(1.0f);
		
		return (int) Math.round(fitness * getMaxFitnessValue());
	}

	@Override
	protected void scale(int scaleCount, int scaleFactor) {
		// TODO Auto-generated method stub

	}

	/**
	 * @param args
	 * @throws Throwable 
	 */
	public static void main(String[] args) throws Throwable {
		try {
			if ( args.length != 1 ) {
				System.exit( -1 );
			}

			// Anji Properties class... file must be in classpath 
			Properties props = new Properties( args[ 0 ] );
            
            String runID = props.getProperty("run.name") + "-" + System.currentTimeMillis();
            String outputDir = props.getProperty("fitness_function.class") + File.separatorChar + runID + File.separatorChar;
            props.setProperty("run.id", ""+runID);
            props.setProperty("output.dir", outputDir);
            
            Evolver evolver = new Evolver();
            
            evolver.init( props );
            evolver.run();
            System.exit( 0 );
		}
		catch ( Throwable th ) {
//			logger.log(Level.SEVERE, th.getMessage());
			throw th;
		}
	}

}
